Web Audio APIã®è©³çްãªè§£èª¬ã§ãWebã¢ããªã±ãŒã·ã§ã³ã«ããããªã¢ã«ã¿ã€ã ãªãŒãã£ãªæäœã®ãã¯ãŒãè§£ãæŸã¡ãŸããããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ã«åããå®è£ ãã³ã³ã»ãããå®è·µçãªäŸãç¶²çŸ ããã¬ã€ãã§ãã
ããã³ããšã³ããªãŒãã£ãªåŠçïŒWeb Audio APIã®ç¿åŸ
仿¥ã®ãã€ãããã¯ãªãŠã§ãã®äžçã§ã¯ãã€ã³ã¿ã©ã¯ãã£ãã§é åçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæãéèŠã§ããèŠèŠçãªæŽŸæãã«å ããŠãèŽèŠèŠçŽ ã¯æ²¡å ¥åã§èšæ¶ã«æ®ãããžã¿ã«ã€ã³ã¿ã©ã¯ã·ã§ã³ãæ§ç¯ããäžã§éèŠãªåœ¹å²ãæãããŸãã匷åãªJavaScript APIã§ããWeb Audio APIã¯ãéçºè ã«ãã©ãŠã¶å ã§çŽæ¥ãªãŒãã£ãªã³ã³ãã³ããçæãåŠçãåæããããã®ããŒã«ãæäŸããŸãããã®å æ¬çãªã¬ã€ãã§ã¯ãWeb Audio APIã®ã³ã¢ã³ã³ã»ãããšå®è·µçãªå®è£ ã«ã€ããŠèª¬æããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã«æŽç·ŽããããªãŒãã£ãªãšã¯ã¹ããªãšã³ã¹ãäœæã§ããããã«ããŸãã
Web Audio APIãšã¯ïŒ
Web Audio APIã¯ãWebã¢ããªã±ãŒã·ã§ã³ã§ãªãŒãã£ãªãåŠçããã³åæããããã«èšèšãããé«ã¬ãã«ã®JavaScript APIã§ããã¢ãžã¥ãŒã«åŒã®ã°ã©ãããŒã¹ã®ã¢ãŒããã¯ãã£ãæäŸãããªãŒãã£ãªãœãŒã¹ããšãã§ã¯ããããã³ãã¹ãã£ããŒã·ã§ã³ãæ¥ç¶ããŠè€éãªãªãŒãã£ãªãã€ãã©ã€ã³ãäœæããŸããäž»ã«åçãç®çãšããåºæ¬çãª<audio>ããã³<video>èŠçŽ ãšã¯ç°ãªããWeb Audio APIã¯ãªãŒãã£ãªä¿¡å·ã现ããå¶åŸ¡ã§ããããããªã¢ã«ã¿ã€ã æäœãåæãããã³é«åºŠãªãšãã§ã¯ãåŠçãå¯èœã«ãªããŸãã
ãã®APIã¯ãããã€ãã®äž»èŠãªã³ã³ããŒãã³ããäžå¿ã«æ§ç¯ãããŠããŸãã
- AudioContext: ãã¹ãŠã®ãªãŒãã£ãªæäœã®äžå¿çãªããããªãŒãã£ãªåŠçã°ã©ãã衚ãããã¹ãŠã®ãªãŒãã£ãªããŒããäœæããããã«äœ¿çšãããŸãã
- ãªãŒãã£ãªããŒã: ãããã¯ãªãŒãã£ãªã°ã©ãã®æ§æèŠçŽ ã§ãããœãŒã¹ïŒãªã·ã¬ãŒã¿ãŒããã€ã¯å ¥åãªã©ïŒããšãã§ã¯ãïŒãã£ã«ã¿ãŒããã£ã¬ã€ãªã©ïŒãããã³ãã¹ãã£ããŒã·ã§ã³ïŒã¹ããŒã«ãŒåºåãªã©ïŒã衚ããŸãã
- æ¥ç¶: ããŒãã¯æ¥ç¶ãããŠãªãŒãã£ãªåŠçãã§ãŒã³ã圢æããŸããããŒã¿ã¯ããœãŒã¹ããŒããããšãã§ã¯ãããŒããééããŠãã¹ãã£ããŒã·ã§ã³ããŒãã«æµããŸãã
ã¯ããã«ïŒAudioContext
ãªãŒãã£ãªã§äœããè¡ãåã«ãAudioContextã€ã³ã¹ã¿ã³ã¹ãäœæããå¿
èŠããããŸããããã¯ãWeb Audio APIå
šäœãžã®ãšã³ããªãã€ã³ãã§ãã
äŸïŒAudioContextã®äœæ
```javascript let audioContext; try { // Standard API */ audioContext = new (window.AudioContext || window.webkitAudioContext)(); console.log('AudioContext created successfully!'); } catch (e) { // Web Audio API is not supported in this browser alert('Web Audio API is not supported in your browser. Please use a modern browser.'); } ```å€ãããŒãžã§ã³ã®ChromeãSafariã§ã¯ããã¬ãã£ãã¯ã¹ä»ãã®webkitAudioContextã䜿çšãããŠããããããã©ãŠã¶ã®äºææ§ã«å¯ŸåŠããããšãéèŠã§ããAudioContextã¯ããã©ãŠã¶ã®èªååçããªã·ãŒã«ããããŠãŒã¶ãŒã€ã³ã¿ã©ã¯ã·ã§ã³ïŒãã¿ã³ã¯ãªãã¯ãªã©ïŒã«å¿ããŠäœæããã®ãçæ³çã§ãã
ãªãŒãã£ãªãœãŒã¹ïŒãµãŠã³ãã®çæãšããŒã
ãªãŒãã£ãªåŠçã¯ããªãŒãã£ãªãœãŒã¹ããå§ãŸããŸããWeb Audio APIã¯ãããã€ãã®ã¿ã€ãã®ãœãŒã¹ããµããŒãããŠããŸãã
1. OscillatorNode: ããŒã³ã®åæ
OscillatorNodeã¯ãåšæçãªæ³¢åœ¢ãžã§ãã¬ãŒã¿ãŒã§ãããµã€ã³æ³¢ãç©åœ¢æ³¢ãã®ãããæ³¢ãäžè§æ³¢ãªã©ã®åºæ¬çãªåæé³ãäœæããã®ã«æé©ã§ãã
äŸïŒãµã€ã³æ³¢ã®äœæãšåç
```javascript if (audioContext) { const oscillator = audioContext.createOscillator(); oscillator.type = 'sine'; // 'sine', 'square', 'sawtooth', 'triangle' oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // A4ããŒãïŒ440 HzïŒ // ãªã·ã¬ãŒã¿ãŒããªãŒãã£ãªã³ã³ããã¹ãã®ãã¹ãã£ããŒã·ã§ã³ïŒã¹ããŒã«ãŒïŒã«æ¥ç¶ããŸã oscillator.connect(audioContext.destination); // ãªã·ã¬ãŒã¿ãŒãéå§ããŸã oscillator.start(); // 1ç§åŸã«ãªã·ã¬ãŒã¿ãŒã忢ããŸã setTimeout(() => { oscillator.stop(); console.log('Sine wave stopped.'); }, 1000); } ```OscillatorNodeã®äž»ãªããããã£ïŒ
typeïŒæ³¢åœ¢ãèšå®ããŸããfrequencyïŒãããããã«ãïŒHzïŒã§å¶åŸ¡ããŸããsetValueAtTimeãlinearRampToValueAtTimeãããã³exponentialRampToValueAtTimeãªã©ã®ã¡ãœããã䜿çšããŠãæéã®çµéã«äŒŽãåšæ³¢æ°ã®å€åãæ£ç¢ºã«å¶åŸ¡ã§ããŸãã
2. BufferSourceNode: ãªãŒãã£ãªãã¡ã€ã«ã®åç
BufferSourceNodeã¯ãAudioBufferã«ããŒãããããªãŒãã£ãªããŒã¿ãåçããŸããããã¯éåžžãçã广é³ãé²é³æžã¿ã®ãªãŒãã£ãªã¯ãªãããåçããããã«äœ¿çšãããŸãã
ãŸãããªãŒãã£ãªãã¡ã€ã«ãååŸããŠãã³ãŒãããå¿ èŠããããŸãã
äŸïŒãªãŒãã£ãªãã¡ã€ã«ã®ããŒããšåç
```javascript async function playSoundFile(url) { if (!audioContext) return; try { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.connect(audioContext.destination); source.start(); // ãµãŠã³ããããã«åçããŸã console.log(`Playing sound from: ${url}`); source.onended = () => { console.log('Sound file playback ended.'); }; } catch (e) { console.error('Error decoding or playing audio data:', e); } } // äœ¿çšæ¹æ³ïŒ // playSoundFile('path/to/your/sound.mp3'); ```AudioContext.decodeAudioData()ã¯ãããŸããŸãªåœ¢åŒïŒMP3ãWAVãOgg Vorbisãªã©ïŒã®ãªãŒãã£ãªããŒã¿ãAudioBufferã«ãã³ãŒãããéåææäœã§ãããã®AudioBufferã¯ãBufferSourceNodeã«å²ãåœãŠãããšãã§ããŸãã
3. MediaElementAudioSourceNode: HTMLMediaElementã®äœ¿çš
ãã®ããŒãã䜿çšãããšãæ¢åã®HTML <audio>ãŸãã¯<video>èŠçŽ ããªãŒãã£ãªãœãŒã¹ãšããŠäœ¿çšã§ããŸããããã¯ãæšæºã®HTMLèŠçŽ ã«ãã£ãŠå¶åŸ¡ãããã¡ãã£ã¢ã«Web Audio APIãšãã§ã¯ããé©çšããå Žåã«åœ¹ç«ã¡ãŸãã
äŸïŒHTMLãªãŒãã£ãªèŠçŽ ãžã®ãšãã§ã¯ãã®é©çš
```javascript // HTMLã«ãªãŒãã£ãªèŠçŽ ããããšä»®å®ããŸãïŒ // if (audioContext) { const audioElement = document.getElementById('myAudio'); const mediaElementSource = audioContext.createMediaElementSource(audioElement); // ããã§ããã®ãœãŒã¹ãä»ã®ããŒãïŒãšãã§ã¯ããªã©ïŒã«æ¥ç¶ã§ããŸã // ãšããããããã¹ãã£ããŒã·ã§ã³ã«çŽæ¥æ¥ç¶ããŸãããïŒ mediaElementSource.connect(audioContext.destination); // JavaScriptã§åçãå¶åŸ¡ããå ŽåïŒ // audioElement.play(); // audioElement.pause(); } ```ãã®ã¢ãããŒãã¯ãåçå¶åŸ¡ããªãŒãã£ãªåŠçã°ã©ãããåé¢ããæè»æ§ãæäŸããŸãã
4. MediaStreamAudioSourceNode: ã©ã€ããªãŒãã£ãªå ¥å
navigator.mediaDevices.getUserMedia()ã䜿çšããŠããŠãŒã¶ãŒã®ãã€ã¯ãŸãã¯ãã®ä»ã®ã¡ãã£ã¢å
¥åããã€ã¹ãããªãŒãã£ãªããã£ããã£ã§ããŸããçµæã®MediaStreamã¯ãMediaStreamAudioSourceNodeã䜿çšããŠWeb Audio APIã«äŸçµŠã§ããŸãã
äŸïŒãã€ã¯å ¥åã®ãã£ããã£ãšåç
```javascript async function startMicInput() { if (!audioContext) return; try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const microphoneSource = audioContext.createMediaStreamSource(stream); // ããã§ããã€ã¯å ¥åãåŠçã§ããŸããããšãã°ããšãã§ã¯ããŸãã¯ãã¹ãã£ããŒã·ã§ã³ã«æ¥ç¶ããŸã microphoneSource.connect(audioContext.destination); console.log('Microphone input captured and playing.'); // 忢ããã«ã¯ïŒ // stream.getTracks().forEach(track => track.stop()); } catch (err) { console.error('Error accessing microphone:', err); alert('Could not access microphone. Please grant permission.'); } } // ãã€ã¯ãéå§ããã«ã¯ïŒ // startMicInput(); ```ãã€ã¯ãžã®ã¢ã¯ã»ã¹ã«ã¯ãŠãŒã¶ãŒã®èš±å¯ãå¿ èŠã§ããããšã«æ³šæããŠãã ããã
ãªãŒãã£ãªåŠçïŒãšãã§ã¯ãã®é©çš
Web Audio APIã®çã®åã¯ããªãŒãã£ãªä¿¡å·ããªã¢ã«ã¿ã€ã ã§åŠçã§ããããšã«ãããŸããããã¯ããœãŒã¹ãšãã¹ãã£ããŒã·ã§ã³ã®éã®åŠçã°ã©ãã«ããŸããŸãªAudioNodeãæ¿å
¥ããããšã§å®çŸãããŸãã
1. GainNode: ããªã¥ãŒã ã³ã³ãããŒã«
GainNodeã¯ããªãŒãã£ãªä¿¡å·ã®ããªã¥ãŒã ãå¶åŸ¡ããŸãããã®gainããããã£ã¯AudioParamã§ãããæéã®çµéã«äŒŽãã¹ã ãŒãºãªããªã¥ãŒã 倿Žãå¯èœã§ãã
äŸïŒãµãŠã³ãã®ãã§ãŒãã€ã³
```javascript // 'source'ãAudioBufferSourceNodeãŸãã¯OscillatorNodeã§ãããšä»®å®ããŸã if (audioContext && source) { const gainNode = audioContext.createGain(); gainNode.gain.setValueAtTime(0, audioContext.currentTime); // ç¡é³ã§éå§ gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2); // 2ç§ãããŠæå€§ããªã¥ãŒã ã«ãã§ãŒã source.connect(gainNode); gainNode.connect(audioContext.destination); source.start(); } ```2. DelayNode: ãšã³ãŒãšãªããŒãã®äœæ
DelayNodeã¯ããªãŒãã£ãªä¿¡å·ã«æéé
å»¶ãå°å
¥ããŸããDelayNodeã®åºåããã®å
¥åã«æ»ãïŒå€ãã®å Žåãå€ã1æªæºã®GainNodeãä»ããŠïŒããšã³ãŒå¹æãäœæã§ããŸããããè€éãªãªããŒãã¯ãè€æ°ã®ãã£ã¬ã€ãšãã£ã«ã¿ãŒã§å®çŸã§ããŸãã
äŸïŒã·ã³ãã«ãªãšã³ãŒã®äœæ
```javascript // 'source'ãAudioBufferSourceNodeãŸãã¯OscillatorNodeã§ãããšä»®å®ããŸã if (audioContext && source) { const delayNode = audioContext.createDelay(); delayNode.delayTime.setValueAtTime(0.5, audioContext.currentTime); // 0.5ç§ã®é å»¶ const feedbackGain = audioContext.createGain(); feedbackGain.gain.setValueAtTime(0.3, audioContext.currentTime); // 30ïŒ ã®ãã£ãŒããã㯠source.connect(audioContext.destination); source.connect(delayNode); delayNode.connect(feedbackGain); feedbackGain.connect(delayNode); // ãã£ãŒãããã¯ã«ãŒã feedbackGain.connect(audioContext.destination); // çŽæ¥ä¿¡å·ãåºåã«éä¿¡ source.start(); } ```3. BiquadFilterNode: åšæ³¢æ°ã®æŽåœ¢
BiquadFilterNodeã¯ããªãŒãã£ãªä¿¡å·ã«2æ¬¡åæ¹åãã£ã«ã¿ãŒãé©çšããŸãããããã®ãã£ã«ã¿ãŒã¯ãåšæ³¢æ°ã³ã³ãã³ãã®æŽåœ¢ãã€ã³ã©ã€ãŒãŒã·ã§ã³ïŒEQïŒå¹æã®äœæãããã³å
±é³Žé³ã®å®è£
ã®ããã®ãªãŒãã£ãªåŠçã®åºæ¬ã§ãã
äžè¬çãªãã£ã«ã¿ãŒã¿ã€ãã«ã¯ã次ã®ãããªãã®ããããŸãã
lowpassïŒäœåšæ³¢æ°ãééãããŸããhighpassïŒé«åšæ³¢æ°ãééãããŸããbandpassïŒç¹å®ã®ç¯å²å ã®åšæ³¢æ°ãééãããŸããlowshelfïŒç¹å®ã®ãã€ã³ãããäžã®åšæ³¢æ°ãããŒã¹ããŸãã¯ã«ããããŸããhighshelfïŒç¹å®ã®ãã€ã³ãããäžã®åšæ³¢æ°ãããŒã¹ããŸãã¯ã«ããããŸããpeakingïŒäžå¿åšæ³¢æ°ä»è¿ã®åšæ³¢æ°ãããŒã¹ããŸãã¯ã«ããããŸããnotchïŒç¹å®ã®åšæ³¢æ°ãåé€ããŸãã
äŸïŒããŒãã¹ãã£ã«ã¿ãŒã®é©çš
```javascript // 'source'ãAudioBufferSourceNodeãŸãã¯OscillatorNodeã§ãããšä»®å®ããŸã if (audioContext && source) { const filterNode = audioContext.createBiquadFilter(); filterNode.type = 'lowpass'; // ããŒãã¹ãã£ã«ã¿ãŒãé©çšããŸã filterNode.frequency.setValueAtTime(1000, audioContext.currentTime); // 1000 Hzã®ã«ãããªãåšæ³¢æ° filterNode.Q.setValueAtTime(1, audioContext.currentTime); // å ±æ¯å å source.connect(filterNode); filterNode.connect(audioContext.destination); source.start(); } ```4. ConvolverNode: ãªã¢ã«ãªãªããŒãã®äœæ
ConvolverNodeã¯ãã€ã³ãã«ã¹å¿çïŒIRïŒããªãŒãã£ãªä¿¡å·ã«é©çšããŸããå®éã®é³é¿ç©ºéïŒéšå±ãããŒã«ãªã©ïŒã®é²é³æžã¿ãªãŒãã£ãªãã¡ã€ã«ã䜿çšããããšã«ããããªã¢ã«ãªæ®é¿å¹æãäœæã§ããŸãã
äŸïŒãµãŠã³ããžã®ãªããŒãã®é©çš
```javascript async function applyReverb(source, reverbImpulseResponseUrl) { if (!audioContext) return; try { // ã€ã³ãã«ã¹å¿çãããŒãããŸã const irResponse = await fetch(reverbImpulseResponseUrl); const irArrayBuffer = await irResponse.arrayBuffer(); const irAudioBuffer = await audioContext.decodeAudioData(irArrayBuffer); const convolver = audioContext.createConvolver(); convolver.buffer = irAudioBuffer; source.connect(convolver); convolver.connect(audioContext.destination); console.log('Reverb applied.'); } catch (e) { console.error('Error loading or applying reverb:', e); } } // 'myBufferSource'ãéå§ãããBufferSourceNodeã§ãããšä»®å®ããŸãïŒ // applyReverb(myBufferSource, 'path/to/your/reverb.wav'); ```ãªããŒãã®å質ã¯ãã€ã³ãã«ã¹å¿çãªãŒãã£ãªãã¡ã€ã«ã®å質ãšç¹æ§ã«å€§ããäŸåããŸãã
ãã®ä»ã®åœ¹ç«ã€ããŒã
AnalyserNodeïŒãªãŒãã£ãªä¿¡å·ã®ãªã¢ã«ã¿ã€ã ã®åšæ³¢æ°ããã³æéé ååæçšãèŠèŠåã«äžå¯æ¬ ã§ããDynamicsCompressorNodeïŒãªãŒãã£ãªä¿¡å·ã®ãã€ãããã¯ã¬ã³ãžãçž®å°ããŸããWaveShaperNodeïŒæªã¿ããã®ä»ã®éç·åœ¢å¹æãé©çšããŸããPannerNodeïŒ3D空éãªãŒãã£ãªå¹æçšã
è€éãªãªãŒãã£ãªã°ã©ãã®æ§ç¯
Web Audio APIã®åã¯ããããã®ããŒãããã§ãŒã³ããŠè€éãªãªãŒãã£ãªåŠçãã€ãã©ã€ã³ãäœæã§ããããšã«ãããŸããäžè¬çãªãã¿ãŒã³ã¯æ¬¡ã®ãšããã§ãã
SourceNode -> EffectNode1 -> EffectNode2 -> ... -> DestinationNode
äŸïŒã·ã³ãã«ãªãšãã§ã¯ããã§ãŒã³ïŒãã£ã«ã¿ãŒãšã²ã€ã³ãåãããªã·ã¬ãŒã¿ãŒïŒ
```javascript if (audioContext) { const oscillator = audioContext.createOscillator(); const filter = audioContext.createBiquadFilter(); const gain = audioContext.createGain(); // ããŒããæ§æããŸã oscillator.type = 'sawtooth'; oscillator.frequency.setValueAtTime(220, audioContext.currentTime); // A3ããŒã filter.type = 'bandpass'; filter.frequency.setValueAtTime(500, audioContext.currentTime); filter.Q.setValueAtTime(5, audioContext.currentTime); // å£ç¬ã®ãããªé³ã®ããã®é«ãå ±é³Ž gain.gain.setValueAtTime(0.5, audioContext.currentTime); // ååã®ããªã¥ãŒã // ããŒããæ¥ç¶ããŸã oscillator.connect(filter); filter.connect(gain); gain.connect(audioContext.destination); // åçãéå§ããŸã oscillator.start(); // æ°ç§åŸã«åæ¢ããŸã setTimeout(() => { oscillator.stop(); console.log('Sawtooth wave with effects stopped.'); }, 3000); } ```ããããŒãã®åºåãè€æ°ã®ä»ã®ããŒãã®å ¥åã«æ¥ç¶ããŠãåå²ãªãŒãã£ãªãã¹ãäœæã§ããŸãã
AudioWorklet: ããã³ããšã³ãã§ã®ã«ã¹ã¿ã DSP
é«åºŠãªãŸãã¯ã«ã¹ã¿ã ã®ããžã¿ã«ä¿¡å·åŠçïŒDSPïŒã¿ã¹ã¯ã®å ŽåãAudioWorklet APIã¯ãå¥ã®å°çšãªãŒãã£ãªã¹ã¬ããã§ã«ã¹ã¿ã JavaScriptã³ãŒããå®è¡ããæ¹æ³ãæäŸããŸããããã«ãããã¡ã€ã³UIã¹ã¬ãããžã®å¹²æžãåé¿ãããããã¹ã ãŒãºã§äºæž¬å¯èœãªãªãŒãã£ãªããã©ãŒãã³ã¹ãä¿èšŒãããŸãã
AudioWorkletã¯ã次ã®2ã€ã®éšåã§æ§æãããŠããŸãã
AudioWorkletProcessorïŒãªãŒãã£ãªã¹ã¬ããã§å®è¡ãããå®éã®ãªãŒãã£ãªåŠçãå®è¡ããJavaScriptã¯ã©ã¹ãAudioWorkletNodeïŒããã»ããµãšå¯Ÿè©±ããããã«ã¡ã€ã³ã¹ã¬ããã§äœæããã«ã¹ã¿ã ããŒãã
æŠå¿µçãªäŸïŒç°¡ç¥åïŒïŒ
my-processor.jsïŒãªãŒãã£ãªã¹ã¬ããã§å®è¡ïŒïŒ
main.jsïŒã¡ã€ã³ã¹ã¬ããã§å®è¡ïŒïŒ
AudioWorkletã¯ããé«åºŠãªãããã¯ã§ãããã«ã¹ã¿ã ã¢ã«ãŽãªãºã ãå¿
èŠãšããããã©ãŒãã³ã¹ãéèŠãªãªãŒãã£ãªã¢ããªã±ãŒã·ã§ã³ã«ã¯äžå¯æ¬ ã§ãã
ãªãŒãã£ãªãã©ã¡ãŒã¿ãŒãšèªåå
å€ãã®AudioNodeã«ã¯ãå®éã«ã¯AudioParamãªããžã§ã¯ãã§ããããããã£ããããŸãïŒäŸïŒfrequencyãgainãdelayTimeïŒããããã®ãã©ã¡ãŒã¿ãŒã¯ãèªååã¡ãœããã䜿çšããŠæéã®çµéãšãšãã«æäœã§ããŸãã
setValueAtTime(value, time)ïŒç¹å®ã®æéã«ãã©ã¡ãŒã¿ãŒã®å€ãèšå®ããŸããlinearRampToValueAtTime(value, time)ïŒæå®ãããæéã«ããã£ãŠãçŸåšã®å€ããæ°ããå€ãžã®ç·åœ¢å€åãäœæããŸããexponentialRampToValueAtTime(value, time)ïŒããªã¥ãŒã ãŸãã¯ãããã®å€æŽã«ãã䜿çšãããææ°é¢æ°çãªå€åãäœæããŸããsetTargetAtTime(target, time, timeConstant)ïŒæå®ãããæé宿°ã§ã¿ãŒã²ããå€ãžã®å€æŽãã¹ã±ãžã¥ãŒã«ããã¹ã ãŒãºã§èªç¶ãªãã©ã³ãžã·ã§ã³ãäœæããŸããstart()ããã³stop()ïŒãã©ã¡ãŒã¿ãŒèªååæ²ç·ã®éå§ãšçµäºãã¹ã±ãžã¥ãŒã«ããŸãã
ãããã®ã¡ãœããã䜿çšãããšãæ£ç¢ºãªå¶åŸ¡ãšè€éãªãšã³ãããŒããå¯èœã«ãªãããªãŒãã£ãªããããã€ãããã¯ã§è¡šçŸåè±ãã«ãªããŸãã
èŠèŠåïŒãªãŒãã£ãªãçãçããšããã
AnalyserNodeã¯ããªãŒãã£ãªèŠèŠåãäœæããããã®æè¯ã®ããŒã«ã§ããåšæ³¢æ°é åãŸãã¯æéé åã®ããããã§çã®ãªãŒãã£ãªããŒã¿ããã£ããã£ã§ããŸãã
äŸïŒCanvas APIã䜿çšããåºæ¬çãªåšæ³¢æ°èŠèŠå
```javascript let analyser; let canvas; let canvasContext; function setupVisualizer(audioSource) { if (!audioContext) return; analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; // 2ã®çޝä¹ã§ããå¿ èŠããããŸã const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); // ãœãŒã¹ãã¢ãã©ã€ã¶ãŒã«æ¥ç¶ããæ¬¡ã«ãã¹ãã£ããŒã·ã§ã³ã«æ¥ç¶ããŸã audioSource.connect(analyser); analyser.connect(audioContext.destination); // ãã£ã³ãã¹ãèšå®ããŸã canvas = document.getElementById('audioVisualizer'); // ãååšãããšä»®å®ããŸã canvasContext = canvas.getContext('2d'); canvas.width = 600; canvas.height = 300; drawVisualizer(dataArray, bufferLength); } function drawVisualizer(dataArray, bufferLength) { requestAnimationFrame(() => drawVisualizer(dataArray, bufferLength)); analyser.getByteFrequencyData(dataArray); // åšæ³¢æ°ããŒã¿ãååŸããŸã canvasContext.clearRect(0, 0, canvas.width, canvas.height); canvasContext.fillStyle = 'rgb(0, 0, 0)'; canvasContext.fillRect(0, 0, canvas.width, canvas.height); const barWidth = (canvas.width / bufferLength) * 2.5; let x = 0; for(let i = 0; i < bufferLength; i++) { const barHeight = dataArray[i]; canvasContext.fillStyle = 'rgb(' + barHeight + ',50,50)'; canvasContext.fillRect(x, canvas.height - barHeight, barWidth, barHeight); x += barWidth + 1; } } // äœ¿çšæ¹æ³ïŒ // 'source'ãOscillatorNodeãŸãã¯BufferSourceNodeã§ãããšä»®å®ããŸãïŒ // setupVisualizer(source); // source.start(); ```fftSizeããããã£ã¯ãé«éããŒãªãšå€æã«äœ¿çšããããµã³ãã«æ°ã決å®ããåšæ³¢æ°åè§£èœãšããã©ãŒãã³ã¹ã«åœ±é¿ãäžããŸããfrequencyBinCountã¯fftSizeã®ååã§ãã
ãã¹ããã©ã¯ãã£ã¹ãšèæ ®äºé
Web Audio APIãå®è£ ããå Žåã¯ã次ã®ãã¹ããã©ã¯ãã£ã¹ã念é ã«çœ®ããŠãã ããã
AudioContextäœæã®ããã®ãŠãŒã¶ãŒã€ã³ã¿ã©ã¯ã·ã§ã³ïŒå¿ ããã¯ãªãã¯ãã¿ãããªã©ã®ãŠãŒã¶ãŒãžã§ã¹ãã£ã«å¿ããŠAudioContextãäœæããŠãã ãããããã«ããããã©ãŠã¶ã®èªååçããªã·ãŒãéµå®ãããããåªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãä¿èšŒãããŸãã- ãšã©ãŒåŠçïŒWeb Audio APIããµããŒããããŠããªãå ŽåããŸãã¯ãªãŒãã£ãªã®ãã³ãŒããŸãã¯åçã倱æããå Žåã«ãé©åã«å¯ŸåŠããŠãã ããã
- ãªãœãŒã¹ç®¡çïŒ
BufferSourceNodeã®å Žåãåºã«ãªãAudioBufferãäžèŠã«ãªã£ãå Žåã«è§£æŸããŠãã¡ã¢ãªãè§£æŸããŠãã ããã - ããã©ãŒãã³ã¹ïŒç¹ã«
AudioWorkletã䜿çšããå Žåã¯ããªãŒãã£ãªã°ã©ãã®è€éãã«æ³šæããŠãã ãããã¢ããªã±ãŒã·ã§ã³ããããã¡ã€ã«ããŠãããã©ãŒãã³ã¹ã®ããã«ããã¯ãç¹å®ããŠãã ããã - ã¯ãã¹ãã©ãŠã¶äºææ§ïŒããŸããŸãªãã©ãŠã¶ããã³ããã€ã¹ã§ãªãŒãã£ãªã®å®è£ ããã¹ãããŸããWeb Audio APIã¯ååã«ãµããŒããããŠããŸããã埮åŠãªéããçºçããå¯èœæ§ããããŸãã
- ã¢ã¯ã»ã·ããªãã£ïŒãªãŒãã£ãªãç¥èŠã§ããªããŠãŒã¶ãŒãèæ ®ããŠãã ããã代æ¿ã®ãã£ãŒãããã¯ã¡ã«ããºã ãæäŸãããããªãŒãã£ãªãç¡å¹ã«ãããªãã·ã§ã³ãæäŸããŸãã
- ã°ããŒãã«ãªãŒãã£ãªåœ¢åŒïŒãªãŒãã£ãªãã¡ã€ã«ãé åžããå Žåã¯ãMP3ãŸãã¯AACã«å ããŠãããå¹ åºãäºææ§ãšããåªããå§çž®ã®ããã«ãOgg VorbisãOpusãªã©ã®åœ¢åŒã®äœ¿çšãæ€èšããŠãã ããã
åœéçãªäŸãšã¢ããªã±ãŒã·ã§ã³
Web Audio APIã¯çšéãåºããããŸããŸãªã°ããŒãã«ç£æ¥ã§ã¢ããªã±ãŒã·ã§ã³ãèŠã€ãããŸãã
- ã€ã³ã¿ã©ã¯ãã£ããã¥ãŒãžãã¯ã¢ããªã±ãŒã·ã§ã³ïŒAbleton LinkïŒWeb Audio APIçµ±åããããŸãïŒã®ãããªãã©ãããã©ãŒã ã¯ãããã€ã¹ããã³å Žæå šäœã§ã®å ±å鳿¥œäœæãå¯èœã«ããŸãã
- ã²ãŒã éçºïŒãã©ãŠã¶ããŒã¹ã®ã²ãŒã ã§ã广é³ãBGMãããã³å¿çæ§ã®é«ããªãŒãã£ãªãã£ãŒãããã¯ãäœæããŸãã
- ããŒã¿ã®é³é¿åïŒè€éãªããŒã¿ã»ããïŒéèåžå ŽããŒã¿ãç§åŠç枬å®ãªã©ïŒããµãŠã³ããšããŠè¡šçŸããåæãšè§£éã容æã«ããŸãã
- ã¯ãªãšã€ãã£ãã³ãŒãã£ã³ã°ãšã¢ãŒãã€ã³ã¹ã¿ã¬ãŒã·ã§ã³ïŒãžã§ãã¬ãŒãã£ããã¥ãŒãžãã¯ãããžã¥ã¢ã«ã¢ãŒãã§ã®ãªã¢ã«ã¿ã€ã ãªãŒãã£ãªæäœãããã³Webãã¯ãããžãŒãæèŒããã€ã³ã¿ã©ã¯ãã£ããªãµãŠã³ãã€ã³ã¹ã¿ã¬ãŒã·ã§ã³ãCSS Creaturesã®ãããªWebãµã€ããå€ãã®ã€ã³ã¿ã©ã¯ãã£ããªã¢ãŒããããžã§ã¯ãã¯ãAPIãå©çšããŠãŠããŒã¯ãªèŽèŠäœéšãå®çŸããŠããŸãã
- ã¢ã¯ã»ã·ããªãã£ããŒã«ïŒèŠèŠéç¢è ãéšãããç°å¢ã®ãŠãŒã¶ãŒã«èŽèŠãã£ãŒãããã¯ãäœæããŸãã
- ä»®æ³çŸå®ãšæ¡åŒµçŸå®ïŒWebXRãšã¯ã¹ããªãšã³ã¹ã§ã空éãªãŒãã£ãªãšæ²¡å ¥åãµãŠã³ãã¹ã±ãŒããå®è£ ããŸãã
çµè«
Web Audio APIã¯ãWebã¢ããªã±ãŒã·ã§ã³ãè±å¯ã§ã€ã³ã¿ã©ã¯ãã£ããªãªãŒãã£ãªã§åŒ·åããããšããŠããããã³ããšã³ãéçºè
ã«ãšã£ãŠäžå¯æ¬ ãªããŒã«ã§ããã·ã³ãã«ãªå¹æé³ããè€éãªåæããã³ãªã¢ã«ã¿ã€ã åŠçãŸã§ããã®æ©èœã¯åºç¯å²ã«ããããŸããAudioContextããªãŒãã£ãªããŒããããã³ã¢ãžã¥ãŒã«åŒã°ã©ãæ§é ã®ã³ã¢ã³ã³ã»ãããçè§£ããããšã«ããããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®æ°ããæ¬¡å
ãéãããšãã§ããŸããAudioWorkletã«ããã«ã¹ã¿ã DSPãšè€éãªèªååãæ¢çŽ¢ãããšãçã«ã°ããŒãã«ãªããžã¿ã«ãªãŒãã£ãšã³ã¹åãã®æå
端ã®ãªãŒãã£ãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®ååãªç¥èãåŸãããŸãã
å®éšãéå§ããããŒãããã§ãŒã³ãããã©ãŠã¶ã§ããªãã®ãµãŠã³ãã®ã¢ã€ãã¢ãçãçããšãããŸãããïŒ